package com.aurora.calculator

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.aurora.calculator.state.CalculatorEvents
import com.aurora.calculator.state.CalculatorOperations
import com.aurora.calculator.state.CalculatorState
import java.math.BigDecimal
import java.math.RoundingMode
import java.util.*

class CalculatorViewModel : ViewModel() {

    var state by mutableStateOf(CalculatorState())

    /**
     * 更新state中的数据
     */
    private fun updateState(
        leftNumber: String = "",
        rightNumber: String = "",
        result: String = "",
        operation: CalculatorOperations? = null
    ) {
        state = state.copy(
            leftNumber = leftNumber,
            rightNumber = rightNumber,
            result = result,
            operation = operation
        )
    }

    // 伴生对象，内部定义的属性可以全局调用
    companion object {
        private const val MAX_NUM_LENGTH = 8
    }

    // 模式选择：根据用户操作类型，选择处理函数
    fun onEvents(event: CalculatorEvents) {
        when (event) {
            is CalculatorEvents.Number -> handleNumber(event.number) // 输入数字
            is CalculatorEvents.Operation -> handleOperation(event.operation) // 输入运算符号
            is CalculatorEvents.Delete -> performDeletion() // 删除一位
            is CalculatorEvents.Decimal -> handleDecimal() // 输入小数点
            is CalculatorEvents.Calculator -> performCalculation() // 计算
            is CalculatorEvents.Clear -> resetCalculator() // 按下AC复位
        }
    }

    private fun resetCalculator() {
        state = CalculatorState()
    }

    private fun performCalculation() {
        // 1.将字符类型的数字 -> BigDecimal对象，用于精准计算
        val leftNumber: BigDecimal = when {
            state.leftNumber.isEmpty() -> return
            else -> BigDecimal(state.leftNumber)
        }
        val rightNumber: BigDecimal = when {
            state.rightNumber.isEmpty() -> return
            else -> BigDecimal(state.rightNumber)
        }


        // 2.校验数的有效性
        when {
            // 使用除法时，除数不能为0
            state.operation == CalculatorOperations.Divide
                    && rightNumber.toDouble() == 0.0 -> {
                updateState(result = "不能除以0")
                return
            }

            // 其余结果等于0的情况
            ((state.operation == CalculatorOperations.Divide || state.operation == CalculatorOperations.Mod) && leftNumber.toDouble() == 0.0)
                    || (state.operation == CalculatorOperations.Multiply && (leftNumber.toDouble() == 0.0 || rightNumber.toDouble() == 0.0))
                    || (state.operation == CalculatorOperations.Mod && rightNumber.toDouble() == 0.0)
                    || (leftNumber.toDouble() == 0.0 && rightNumber.toDouble() == 0.0) -> {
                updateState(result = "0")
                return
            }
        }

        // 根据输入的运算符选择相应的计算函数
        // 转换为字符串，并小写化
        val result = when (state.operation) {
            CalculatorOperations.Add -> leftNumber.add(rightNumber)
            CalculatorOperations.Subtract -> leftNumber.subtract(rightNumber)
            CalculatorOperations.Multiply -> leftNumber.multiply(rightNumber)
            CalculatorOperations.Divide -> leftNumber.divide(rightNumber, 10, RoundingMode.UP)
            CalculatorOperations.Mod -> leftNumber.remainder(rightNumber)
            null -> return
        }.toString().lowercase(Locale.getDefault())

        updateState(result = result)
    }

    private fun handleDecimal() {
        if (state.operation == null
            && !state.leftNumber.contains(".")
            && state.leftNumber.isNotBlank()
        ) {
            state = state.copy(leftNumber = state.leftNumber + ".")
            return
        }
        if (!state.rightNumber.contains(".")
            && state.rightNumber.isNotBlank()
        ) {
            state = state.copy(rightNumber = state.rightNumber + ".")
            return
        }

    }

    private fun performDeletion() {
        when {
            state.rightNumber.isNotBlank() -> state = state.copy(
                rightNumber = state.rightNumber.dropLast(1)
            )

            state.operation != null -> state = state.copy(
                operation = null
            )

            state.leftNumber.isNotBlank() -> state = state.copy(
                leftNumber = state.leftNumber.dropLast(1)
            )
        }
    }

    private fun handleOperation(operation: CalculatorOperations) {
        if (state.leftNumber.isNotBlank()) {
            state = state.copy(operation = operation)
        }
    }

    private fun handleNumber(number: String) {
        if (state.operation == null) {
            // 左侧数字处理逻辑
            // 如果左侧数字为0，用户输入非小数点数字时，替换0
            if (state.leftNumber == "0")
                state = state.copy(leftNumber = number)
            // 正常输入数值
            else if (state.leftNumber.length < MAX_NUM_LENGTH)
                state = state.copy(leftNumber = state.leftNumber + number)
        } else {
            // 右侧数字处理逻辑，与左侧类似
            if (state.rightNumber == "0")
                state = state.copy(rightNumber = number)
            else if (state.rightNumber.length < MAX_NUM_LENGTH)
                state = state.copy(rightNumber = state.rightNumber + number)
        }
    }

}